#ifndef ABSTRACT_ELLIPSE_GRAPHIC_ITEM_H
#define ABSTRACT_ELLIPSE_GRAPHIC_ITEM_H

#include "_qhashhelper.h"

#include <ellipsegraphicitem.h>
#include <ieditoritem.h>
#include <inodedata.h>
#include <palette.h>

#include <QtCore/QUuid>
#include <QtGui/QGraphicsEllipseItem>
#include <QtGui/QPixmap>

namespace swp
{
class ConnectionPoint;

class AbstractEllipseGraphicItem : public gui::EllipseGraphicItem,
    public core::IGraphicEditorItem
{
private:
    enum HighlightType
    {
        Selection,
        Connect
    };

public:
    AbstractEllipseGraphicItem(QGraphicsItem* parent = 0);
    AbstractEllipseGraphicItem(const QRectF& rect,
        core::IGraphicItemContent* content = 0, QGraphicsItem* parent = 0);
    virtual ~AbstractEllipseGraphicItem();

    virtual void setRectF(const QRectF& rect);

    // IGraphicEditorItem
    QPixmap thumbnail(core::ThumbnailRole role,
       int size = -1) const;

    void editorModeChange();

    void setContent(core::IGraphicItemContent* content);

    core::IGraphicItemContent* content() const;

    void setPalette(const core::Palette* const palette);

    virtual int paletteType() const;

    void scaleToFitContent();

    void handleContentRefresh();

    void handleConnectorPositionChange();

    void handleSelfConnect(core::IGraphicEditorItem* connector,
        const QPointF& cursorPos, bool previousSelfConnect = false);

    void ensureHandlesGeometryChanges(bool enabled);

    QPointF nearestConnectionPoint(const QPointF& to,
        core::ConnectionDirection direction) const;

    virtual void handleSceneResize();

    QList<core::ConnectionData> connections() const;
    void connectionsRefreshed();

    IEditorItem* parentEditorItem(core::IEditorItem* parent) const;
    void setParentEditorItem(core::IEditorItem* parent);

    core::IDocumentData* parentDocumentData() const;
    void setParentDocumentData(core::IDocumentData* data);

    virtual bool isModel() const;
    virtual bool isGraphic() const;
    virtual bool isText() const;

    QUuid id() const;

    // ISerializable
    bool doActionForProperty(const QString& property,
        const QVariantList& value,
        const core::SerializationEngine& helper);
    void deserializationFinished(bool ok);
    QHash<QString, QVariantList> serializationData(
        const core::SerializationEngine& helper) const;

    // INodeData
    void registerNode(core::Node* node);
    const core::Node* const node() const;

    // QGraphicsPolygonItem
    virtual QRectF boundingRect() const;
    virtual QPainterPath shape() const;
    virtual int type() const;

protected:
    virtual QVariant itemChange(GraphicsItemChange change,
        const QVariant &value);

    virtual void refreshAuxiliaryLayers();

    virtual QList<QPointF> scalePoints() const = 0;
    virtual QList<QPointF> connectPoints() const = 0;
    virtual QList<QPointF> connectPointsForIncoming() const;
    virtual QList<QPointF> connectPointsForOutgoing() const;
    virtual QList<QPointF> selfConnectAnchorPoints() const = 0;
    virtual QList<int> selfConnectAnchorMappings() const;

    void setContentAlignment(int alignment);

    virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);

    virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);

private:
    void createBasicLookAndFeel();
    void createHighlight(HighlightType type, bool valid = true);
    void createTransformationMatrix();
    void createConnectPoints(bool valid);
    void deleteHighlight();
    void deleteTransformationMatrix();
    void deleteConnectPoints();
    void recreateSelectHighlight();
    void checkConnectHighlight();
    void checkConnectPoints();
    void updateConnectionPositions();
    void refreshContentPosition();
    void refreshPalette();
    int connectorForConnection(const core::ConnectionData& data) const;
    QPainterPath pureShape() const;
    int anchorIndex(int index) const;

protected:
    QUuid m_id;
    bool m_isInConnectMode;
    QPointF m_lastPosition;
    QRectF m_rect;
    core::IGraphicItemContent* m_content;
    int m_contentAlignment;
    mutable QPixmap m_thumbnail;
    QGraphicsEllipseItem* m_selectionHighlight;
    QGraphicsEllipseItem* m_connectHighlight;
    QGraphicsEllipseItem* m_transformMatrix;
    mutable QList<QPointF> m_connectPoints;
    QList<ConnectionPoint* > m_connectPointItems;
    core::IEditorItem* m_parentItem;
    core::IDocumentData* m_documentData;
    QList<core::ConnectionData> m_connections;
    QHash<core::ConnectionData, int> m_connectionToConnectorMapping;
    const core::Palette* m_palette;
    core::Node* m_node;
};

} // namespace swp

#endif
